Skip to content

Add Tap to Add button in card form#12299

Merged
samer-stripe merged 1 commit intomasterfrom
samer/tap-to-add-card-form-button
Feb 5, 2026
Merged

Add Tap to Add button in card form#12299
samer-stripe merged 1 commit intomasterfrom
samer/tap-to-add-card-form-button

Conversation

@samer-stripe
Copy link
Collaborator

@samer-stripe samer-stripe commented Feb 3, 2026

Summary

Add Tap to Add button in card form

Motivation

Allows for launching Tap to Add from the card form

Testing

  • Added tests
  • Modified tests
  • Manually verified

@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2026

Diffuse output:

OLD: paymentsheet-example-release-master.apk (signature: V1, V2)
NEW: paymentsheet-example-release-pr.apk (signature: V1, V2)

          │              compressed              │           uncompressed           
          ├─────────────┬─────────────┬──────────┼───────────┬───────────┬──────────
 APK      │ old         │ new         │ diff     │ old       │ new       │ diff     
──────────┼─────────────┼─────────────┼──────────┼───────────┼───────────┼──────────
      dex │       5 MiB │       5 MiB │   +3 KiB │  11.1 MiB │  11.1 MiB │ +2.4 KiB 
     arsc │     3.6 MiB │     3.6 MiB │   +844 B │   3.6 MiB │   3.6 MiB │   +844 B 
 manifest │     5.7 KiB │     5.7 KiB │      0 B │  30.2 KiB │  30.2 KiB │      0 B 
      res │ 1,006.4 KiB │ 1,007.2 KiB │   +866 B │   1.7 MiB │   1.7 MiB │ +1.7 KiB 
   native │   949.9 KiB │   949.9 KiB │      0 B │   2.5 MiB │   2.5 MiB │      0 B 
    asset │    27.1 KiB │    27.1 KiB │    +45 B │  47.7 KiB │  47.8 KiB │    +45 B 
    other │   222.3 KiB │   222.4 KiB │    +64 B │ 448.6 KiB │ 448.8 KiB │   +164 B 
──────────┼─────────────┼─────────────┼──────────┼───────────┼───────────┼──────────
    total │    10.7 MiB │    10.7 MiB │ +4.8 KiB │  19.3 MiB │  19.3 MiB │ +5.1 KiB 

         │         raw          │              unique              
         ├───────┬───────┬──────┼───────┬───────┬──────────────────
 DEX     │ old   │ new   │ diff │ old   │ new   │ diff             
─────────┼───────┼───────┼──────┼───────┼───────┼──────────────────
   files │     2 │     2 │    0 │       │       │                  
 strings │ 58673 │ 58715 │  +42 │ 52415 │ 52419 │ +4 (+55 -51)     
   types │ 20703 │ 20751 │  +48 │ 17552 │ 17553 │ +1 (+48 -47)     
 classes │ 14736 │ 14737 │   +1 │ 14736 │ 14737 │ +1 (+15 -14)     
 methods │ 78470 │ 78434 │  -36 │ 73784 │ 73790 │ +6 (+4936 -4930) 
  fields │ 51543 │ 51564 │  +21 │ 49297 │ 49302 │ +5 (+2965 -2960) 

 ARSC    │ old  │ new  │ diff       
─────────┼──────┼──────┼────────────
 configs │  325 │  325 │  0         
 entries │ 6978 │ 6980 │ +2 (+2 -0)
APK
      compressed      │     uncompressed     │                                
───────────┬──────────┼───────────┬──────────┤                                
 size      │ diff     │ size      │ diff     │ path                           
───────────┼──────────┼───────────┼──────────┼────────────────────────────────
   4.2 MiB │ +6.7 KiB │   9.4 MiB │   +8 KiB │ ∆ classes.dex                  
 779.4 KiB │ -3.7 KiB │   1.7 MiB │ -5.6 KiB │ ∆ classes2.dex                 
     866 B │   +866 B │   1.7 KiB │ +1.7 KiB │ + res/WH.xml                   
   3.6 MiB │   +844 B │   3.6 MiB │   +844 B │ ∆ resources.arsc               
  10.6 KiB │    +49 B │  10.5 KiB │    +49 B │ ∆ assets/dexopt/baseline.prof  
  58.1 KiB │    +35 B │ 128.8 KiB │    +82 B │ ∆ META-INF/CERT.SF             
  54.7 KiB │    +29 B │ 128.8 KiB │    +82 B │ ∆ META-INF/MANIFEST.MF         
   1.3 KiB │     -4 B │   1.1 KiB │     -4 B │ ∆ assets/dexopt/baseline.profm 
───────────┼──────────┼───────────┼──────────┼────────────────────────────────
   8.7 MiB │ +4.8 KiB │    15 MiB │ +5.1 KiB │ (total)
DEX
STRINGS:

   old   │ new   │ diff         
  ───────┼───────┼──────────────
   52415 │ 52419 │ +4 (+55 -51) 
  
  + FailedCollection(error=
  + Lad/h;
  + Lad/i;
  + Lad/j;
  + Lad/k;
  + Landroidx/lifecycle/a1_a;
  + Landroidx/lifecycle/t0_a;
  + Lgj/n;
  + Lil/y4;
  + Ln0/c2;
  + Ln2/i2;
  + Lp/m3;
  + Lxh/k0;
  + Ly/a1;
  + Lz2/t;
  + Not handled!
  + VLLLLLZLLLZLLLZLLZLLL
  + VLLLZLLLLL
  + [Landroidx/lifecycle/m;
  + [Landroidx/lifecycle/n0;
  + [Landroidx/lifecycle/r;
  + [Lbk/i6;
  + [Lbk/n;
  + [Lbk/o6;
  + [Lbk/t2;
  + [Lbk/z1;
  + [Lgd/c;
  + [Lil/p3;
  + [Lil/r1;
  + [Lil/r3;
  + [Lil/u1;
  + [Lj0/j0;
  + [Lmi/u;
  + [Ln2/a1;
  + [Ln2/d1;
  + [Ln2/g2;
  + [Ln2/h0;
  + [Ln2/i2;
  + [Ln2/j0;
  + [Ln2/m0;
  + [Ln2/n1;
  + [Ln2/t1;
  + [Ln2/w0;
  + [Ln2/z;
  + [Lnf/s;
  + [Lxh/z;
  + [Ly3/f;
  + [Lz2/e;
  + r1
  + r8-map-id-fc1d28ebae80901551f19af559d86274c95c5b0ba7892fbe2fa5f5878cd7b1de
  + ~~R8{"backend":"dex","compilation-mode":"release","has-checksums":false,"min-api":21,"pg-map-id":"fc1d28ebae80901551f19af559d86274c95c5b0ba7892fbe2fa5f5878cd7b1de","r8-mode":"full","version":"8.13.17"}
  + Lvl/k;
  + [Lil/g2;
  + [Lil/m3;
  + [Lil/n1;
  
  - Landroidx/lifecycle/b1_a;
  - Landroidx/lifecycle/s1;
  - Landroidx/lifecycle/t1;
  - Landroidx/lifecycle/u0_a;
  - Lbk/n7;
  - Lh4/m;
  - Lj0/f1;
  - Lnf/y;
  - Lp4/p;
  - Lw0/q;
  - Ly0/w0;
  - Ly3/h;
  - Lze/i;
  - VLLLLLZLLLZLLLZLLZLL
  - VLLLZLLLL
  - [Landroidx/lifecycle/n;
  - [Landroidx/lifecycle/o0;
  - [Landroidx/lifecycle/t;
  - [Lbk/a2;
  - [Lbk/l6;
  - [Lbk/p6;
  - [Lbk/p;
  - [Lbk/u2;
  - [Lgd/b;
  - [Lil/o3;
  - [Lil/q3;
  - [Lil/t1;
  - [Lj0/k0;
  - [Lmi/r;
  - [Ln2/c1;
  - [Ln2/f2;
  - [Ln2/g0;
  - [Ln2/h2;
  - [Ln2/i0;
  - [Ln2/l0;
  - [Ln2/l1;
  - [Ln2/s1;
  - [Ln2/v0;
  - [Ln2/y0;
  - [Ln2/y;
  - [Lnf/x;
  - [Lxh/y;
  - [Ly3/g;
  - [Lz2/d;
  - r8-map-id-162cc8dd05b2423369050f32dff0ae63acec53648fad0e727f8ae81cddb85b20
  - ~~R8{"backend":"dex","compilation-mode":"release","has-checksums":false,"min-api":21,"pg-map-id":"162cc8dd05b2423369050f32dff0ae63acec53648fad0e727f8ae81cddb85b20","r8-mode":"full","version":"8.13.17"}
  - Lmm/b;
  - [Lil/e2;
  - [Lil/l3;
  - [Lil/m1;
  - [Lil/p1;
  

TYPES:

   old   │ new   │ diff         
  ───────┼───────┼──────────────
   17552 │ 17553 │ +1 (+48 -47) 
  
  + Lad/h;
  + Lad/i;
  + Lad/j;
  + Lad/k;
  + Landroidx/lifecycle/a1_a;
  + Landroidx/lifecycle/t0_a;
  + Lgj/n;
  + Lil/y4;
  + Ln0/c2;
  + Ln2/i2;
  + Lp/m3;
  + Lxh/k0;
  + Ly/a1;
  + Lz2/t;
  + [Landroidx/lifecycle/m;
  + [Landroidx/lifecycle/n0;
  + [Landroidx/lifecycle/r;
  + [Lbk/i6;
  + [Lbk/n;
  + [Lbk/o6;
  + [Lbk/t2;
  + [Lbk/z1;
  + [Lgd/c;
  + [Lil/p3;
  + [Lil/r1;
  + [Lil/r3;
  + [Lil/u1;
  + [Lj0/j0;
  + [Lmi/u;
  + [Ln2/a1;
  + [Ln2/d1;
  + [Ln2/g2;
  + [Ln2/h0;
  + [Ln2/i2;
  + [Ln2/j0;
  + [Ln2/m0;
  + [Ln2/n1;
  + [Ln2/t1;
  + [Ln2/w0;
  + [Ln2/z;
  + [Lnf/s;
  + [Lxh/z;
  + [Ly3/f;
  + [Lz2/e;
  + Lvl/k;
  + [Lil/g2;
  + [Lil/m3;
  + [Lil/n1;
  
  - Landroidx/lifecycle/b1_a;
  - Landroidx/lifecycle/s1;
  - Landroidx/lifecycle/t1;
  - Landroidx/lifecycle/u0_a;
  - Lbk/n7;
  - Lh4/m;
  - Lj0/f1;
  - Lnf/y;
  - Lp4/p;
  - Lw0/q;
  - Ly0/w0;
  - Ly3/h;
  - Lze/i;
  - [Landroidx/lifecycle/n;
  - [Landroidx/lifecycle/o0;
  - [Landroidx/lifecycle/t;
  - [Lbk/a2;
  - [Lbk/l6;
  - [Lbk/p6;
  - [Lbk/p;
  - [Lbk/u2;
  - [Lgd/b;
  - [Lil/o3;
  - [Lil/q3;
  - [Lil/t1;
  - [Lj0/k0;
  - [Lmi/r;
  - [Ln2/c1;
  - [Ln2/f2;
  - [Ln2/g0;
  - [Ln2/h2;
  - [Ln2/i0;
  - [Ln2/l0;
  - [Ln2/l1;
  - [Ln2/s1;
  - [Ln2/v0;
  - [Ln2/y0;
  - [Ln2/y;
  - [Lnf/x;
  - [Lxh/y;
  - [Ly3/g;
  - [Lz2/d;
  - Lmm/b;
  - [Lil/e2;
  - [Lil/l3;
  - [Lil/m1;
  - [Lil/p1;
  

METHODS:

   old   │ new   │ diff             
  ───────┼───────┼──────────────────
   73784 │ 73790 │ +6 (+4936 -4930) 
  
  + a.a A(boolean, boolean, boolean, boolean, b, String, String, String, Function0, String, r, k1, Function3, t, int, int, int)
  + a.a A0(p)
  + a.a B(String, boolean, Function0, r, boolean, boolean, boolean, Function0, t, int, int)
  + a.a B0()
  + a.a C(String, long, p0, boolean, boolean, boolean, t, int)
  + a.a C0(Context, int) → int
  + a.a D(b, long, boolean, boolean, Function0, t, int)
  + a.a E(boolean, v0, Function3, r, d1, b, t, int)
  + a.a F(v0, Function3, r, f1, b, t, int)
  + a.a G(boolean, boolean, v0, r, b, t, int)
  + a.a H(boolean, boolean, b, String, String, String, k1, r, t, int)
  + a.a I(k1, boolean, boolean, v0, r, Function3, Function0, b, t, int)
  + a.a J(boolean,
...✂
ARSC
ENTRIES:

   old  │ new  │ diff       
  ──────┼──────┼────────────
   6978 │ 6980 │ +2 (+2 -0) 
  + drawable/stripe_ic_nfc_tap
  + string/stripe_tap_to_add_card_button_label

@samer-stripe samer-stripe force-pushed the samer/tap-to-add-card-form-button branch from 30f1989 to 7667c3a Compare February 3, 2026 21:11
ScanCardButtonUI(
enabled = enabled,
cardScanGoogleLauncher = cardScanLauncher
)
Copy link
Collaborator Author

@samer-stripe samer-stripe Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a large refactor here we can do for Scan card but it requires the foundations from this PR and a follow up PR. It's a relatively expensive engineering refactor but we should create a task to do it to make ScanCard a CardDetailsAction.

@samer-stripe
Copy link
Collaborator Author

Will also fix the strings task once approved!

@samer-stripe samer-stripe marked this pull request as ready for review February 3, 2026 21:38
@samer-stripe samer-stripe requested review from a team as code owners February 3, 2026 21:38

fun shouldAutomaticallyLaunchCardScan(): Boolean {
return automaticallyLaunchedCardScanFormDataHelper?.shouldLaunchCardScanAutomatically == true
return cardDetailsAction == null &&
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would we want to prevent launching card scan in this case? My expectation would be for TTA and automatically launching card scan to be very separate features

It would probably be confusing if someone wanted to launch card scan automatically and then enabling TTA prevented that from happening

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's because TTA will be launching automatically instead of card scan. This is implemented in #12300.

}

@Test
fun `createFormElements has null cardDetailsAction when tap to add is not supported`() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these tests feel a bit like they are testing implementation details -- why exactly do we care about this being null specifically? do we want a certain form element to be shown or not? could we test for that instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually testing to ensure we have no card details action if tap to add is not supported which should be the case. In a future refactor, this would be replaced by either card scan or tap to add.

@samer-stripe samer-stripe merged commit 2fa7da7 into master Feb 5, 2026
25 of 26 checks passed
@samer-stripe samer-stripe deleted the samer/tap-to-add-card-form-button branch February 5, 2026 00:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants